const express = require('express')
const cors = require('cors')
const neo4j = require('neo4j-driver')
require('dotenv').config()

const app = express()
const PORT = process.env.PORT || 3001

// 中间件
app.use(cors())
app.use(express.json({ limit: '50mb' }))
app.use(express.urlencoded({ extended: true, limit: '50mb' }))

// Neo4j 导入 API
app.post('/api/neo4j/import', async (req, res) => {
  let driver = null
  
  try {
    const { knowledgeGraph, neo4jConfig, importMode = 'incremental' } = req.body
    
    if (!knowledgeGraph || !neo4jConfig) {
      return res.status(400).json({
        success: false,
        message: '缺少必要的参数：knowledgeGraph 或 neo4jConfig'
      })
    }
    
    console.log('收到导入请求')
    console.log('请求体中的importMode:', importMode)
    console.log('importMode类型:', typeof importMode)
    console.log('Neo4j 配置:', {
      uri: neo4jConfig.uri,
      username: neo4jConfig.username,
      password: '***'
    })
    console.log(`开始导入，模式: ${importMode}`)
    
    // 创建 Neo4j 驱动
    driver = neo4j.driver(
      neo4jConfig.uri,
      neo4j.auth.basic(neo4jConfig.username, neo4jConfig.password)
    )
    
    // 验证连接
    await driver.verifyConnectivity()
    console.log('Neo4j 连接成功')
    
    const session = driver.session()
    
    try {
      // 根据导入模式决定是否清空数据
      console.log('检查导入模式条件:', importMode, '=== "rebuild":', importMode === 'rebuild')
      if (importMode === 'rebuild') {
        console.log('清空现有数据...')
        await session.run('MATCH (n) DETACH DELETE n')
      } else {
        console.log('增量导入模式，保留现有数据...')
      }
      
      // 创建约束和索引
      console.log('创建约束和索引...')
      const constraints = [
        'CREATE CONSTRAINT IF NOT EXISTS FOR (t:Topic) REQUIRE t.id IS UNIQUE',
        'CREATE CONSTRAINT IF NOT EXISTS FOR (s:Subtopic) REQUIRE s.id IS UNIQUE',
        'CREATE CONSTRAINT IF NOT EXISTS FOR (k:KnowledgePoint) REQUIRE k.id IS UNIQUE',
        'CREATE CONSTRAINT IF NOT EXISTS FOR (c:Concept) REQUIRE c.id IS UNIQUE',
        'CREATE CONSTRAINT IF NOT EXISTS FOR (l:Level) REQUIRE l.id IS UNIQUE'
      ]
      
      for (const constraint of constraints) {
        try {
          await session.run(constraint)
        } catch (error) {
          console.warn(`约束创建警告: ${error.message}`)
        }
      }
      
      let progress = 0
      const totalSteps = 6
      
      // 1. 导入层级
      console.log('导入层级数据...')
      if (knowledgeGraph.levels && knowledgeGraph.levels.length > 0) {
        for (const level of knowledgeGraph.levels) {
          await session.run(
            'MERGE (l:Level {id: $id}) SET l.name = $name, l.description = $description, l.order = $order',
            level
          )
        }
      }
      progress = Math.round((1 / totalSteps) * 100)
      
      // 2. 导入主题
      console.log('导入主题数据...')
      if (knowledgeGraph.topics && knowledgeGraph.topics.length > 0) {
        for (const topic of knowledgeGraph.topics) {
          await session.run(
            'MERGE (t:Topic {id: $id}) SET t.name = $name, t.description = $description, t.level_id = $level_id, t.difficulty = $difficulty',
            topic
          )
        }
      }
      progress = Math.round((2 / totalSteps) * 100)
      
      // 3. 导入子主题
      console.log('导入子主题数据...')
      if (knowledgeGraph.subtopics && knowledgeGraph.subtopics.length > 0) {
        for (const subtopic of knowledgeGraph.subtopics) {
          await session.run(
            'MERGE (s:Subtopic {id: $id}) SET s.name = $name, s.description = $description, s.topic_id = $topic_id, s.difficulty = $difficulty',
            subtopic
          )
        }
      }
      progress = Math.round((3 / totalSteps) * 100)
      
      // 4. 导入知识点
      console.log('导入知识点数据...')
      if (knowledgeGraph.knowledge_points && knowledgeGraph.knowledge_points.length > 0) {
        for (const kp of knowledgeGraph.knowledge_points) {
          await session.run(
            'MERGE (k:KnowledgePoint {id: $id}) SET k.name = $name, k.description = $description, k.content = $content, k.subtopic_id = $subtopic_id, k.difficulty = $difficulty, k.examples = $examples',
            {
              ...kp,
              examples: JSON.stringify(kp.examples || [])
            }
          )
        }
      }
      progress = Math.round((4 / totalSteps) * 100)
      
      // 5. 导入概念
      console.log('导入概念数据...')
      if (knowledgeGraph.concepts && knowledgeGraph.concepts.length > 0) {
        for (const concept of knowledgeGraph.concepts) {
          await session.run(
            'MERGE (c:Concept {id: $id}) SET c.name = $name, c.definition = $definition, c.knowledge_point_id = $knowledge_point_id, c.difficulty = $difficulty',
            concept
          )
        }
      }
      progress = Math.round((5 / totalSteps) * 100)
      
      // 6. 创建关系
      console.log('创建关系...')
      if (knowledgeGraph.relationships && knowledgeGraph.relationships.length > 0) {
        console.log('关系数据示例:', JSON.stringify(knowledgeGraph.relationships[0], null, 2))
        for (const rel of knowledgeGraph.relationships) {
          console.log('处理关系:', { type: rel.type, from_id: rel.from_id, to_id: rel.to_id })
          const query = `
            MATCH (from {id: $from_id}), (to {id: $to_id})
            MERGE (from)-[r:${rel.type}]->(to)
            SET r.properties = $properties
          `
          await session.run(query, {
            from_id: rel.from_id,
            to_id: rel.to_id,
            properties: JSON.stringify(rel.properties || {})
          })
        }
      }
      
      // 创建层次关系
      console.log('创建层次关系...')
      
      // Topic -> Level
      await session.run(`
        MATCH (t:Topic), (l:Level)
        WHERE t.level_id = l.id
        MERGE (t)-[:BELONGS_TO]->(l)
      `)
      
      // Subtopic -> Topic
      await session.run(`
        MATCH (s:Subtopic), (t:Topic)
        WHERE s.topic_id = t.id
        MERGE (s)-[:BELONGS_TO]->(t)
      `)
      
      // KnowledgePoint -> Subtopic
      await session.run(`
        MATCH (k:KnowledgePoint), (s:Subtopic)
        WHERE k.subtopic_id = s.id
        MERGE (k)-[:BELONGS_TO]->(s)
      `)
      
      // Concept -> KnowledgePoint
      await session.run(`
        MATCH (c:Concept), (k:KnowledgePoint)
        WHERE c.knowledge_point_id = k.id
        MERGE (c)-[:BELONGS_TO]->(k)
      `)
      
      progress = 100
      
      // 获取导入统计
      const stats = await session.run(`
        MATCH (t:Topic), (s:Subtopic), (k:KnowledgePoint), (c:Concept), (l:Level)
        OPTIONAL MATCH ()-[r]->()
        RETURN 
          count(DISTINCT t) as topics,
          count(DISTINCT s) as subtopics,
          count(DISTINCT k) as knowledge_points,
          count(DISTINCT c) as concepts,
          count(DISTINCT l) as levels,
          count(DISTINCT r) as relationships
      `)
      
      const statistics = stats.records[0].toObject()
      
      console.log('导入完成！', statistics)
      
      res.json({
        success: true,
        message: '知识图谱数据已成功导入到 Neo4j 数据库',
        statistics: {
          topics: statistics.topics.toNumber(),
          subtopics: statistics.subtopics.toNumber(),
          knowledge_points: statistics.knowledge_points.toNumber(),
          concepts: statistics.concepts.toNumber(),
          levels: statistics.levels.toNumber(),
          relationships: statistics.relationships.toNumber()
        }
      })
      
    } finally {
      await session.close()
    }
    
  } catch (error) {
    console.error('导入错误:', error)
    
    let errorMessage = '导入过程中发生错误'
    
    if (error.code === 'ServiceUnavailable') {
      errorMessage = 'Neo4j 数据库连接失败，请检查数据库是否运行以及连接配置'
    } else if (error.code === 'Neo.ClientError.Security.Unauthorized') {
      errorMessage = 'Neo4j 认证失败，请检查用户名和密码'
    } else if (error.message) {
      errorMessage = error.message
    }
    
    res.status(500).json({
      success: false,
      message: errorMessage,
      error: error.message
    })
  } finally {
    if (driver) {
      await driver.close()
    }
  }
})

// 健康检查端点
app.get('/api/health', (req, res) => {
  res.json({ status: 'OK', message: 'Neo4j Import Server is running' })
})

// Neo4j 查询端点
app.post('/api/neo4j/query', async (req, res) => {
  let driver = null
  
  try {
    const { cypherQuery, neo4jConfig } = req.body
    
    if (!cypherQuery || !neo4jConfig) {
      return res.status(400).json({
        success: false,
        message: '缺少必要的参数：cypherQuery 或 neo4jConfig'
      })
    }
    
    // 创建 Neo4j 驱动
    driver = neo4j.driver(
      neo4jConfig.uri,
      neo4j.auth.basic(neo4jConfig.username, neo4jConfig.password)
    )
    
    // 验证连接
    await driver.verifyConnectivity()
    console.log('Neo4j 连接成功，执行查询:', cypherQuery)
    
    const session = driver.session()
    
    try {
      const result = await session.run(cypherQuery)
      
      // 处理查询结果
      const nodes = new Map()
      const edges = []
      const records = []
      
      result.records.forEach((record) => {
        const recordData = {}
        
        record.keys.forEach((key) => {
          const value = record.get(key)
          recordData[key] = value
          
          // 处理节点
          if (value && typeof value === 'object' && value.labels) {
            const nodeId = value.identity.toString()
            if (!nodes.has(nodeId)) {
              nodes.set(nodeId, {
                id: nodeId,
                label: value.properties.name || value.properties.title || `Node ${nodeId}`,
                group: value.labels[0] || 'Unknown',
                properties: value.properties
              })
            }
          }
          
          // 处理关系
          if (value && typeof value === 'object' && value.type) {
            edges.push({
              id: value.identity.toString(),
              from: value.start.toString(),
              to: value.end.toString(),
              label: value.type,
              properties: value.properties
            })
          }
        })
        
        records.push(recordData)
      })
      
      const queryResult = {
        nodes: Array.from(nodes.values()),
        edges: edges,
        records: records
      }
      
      console.log(`查询完成，返回 ${queryResult.nodes.length} 个节点，${queryResult.edges.length} 个关系，${queryResult.records.length} 条记录`)
      
      res.json({
        success: true,
        data: queryResult
      })
      
    } finally {
      await session.close()
    }
    
  } catch (error) {
    console.error('查询错误:', error)
    
    let errorMessage = '查询过程中发生错误'
    
    if (error.code === 'ServiceUnavailable') {
      errorMessage = 'Neo4j 数据库连接失败，请检查数据库是否运行以及连接配置'
    } else if (error.code === 'Neo.ClientError.Security.Unauthorized') {
      errorMessage = 'Neo4j 认证失败，请检查用户名和密码'
    } else if (error.message) {
      errorMessage = error.message
    }
    
    res.status(500).json({
      success: false,
      message: errorMessage,
      error: error.message
    })
  } finally {
    if (driver) {
      await driver.close()
    }
  }
})

// 测试 Neo4j 连接端点
app.post('/api/neo4j/test', async (req, res) => {
  let driver = null
  
  try {
    const { neo4jConfig } = req.body
    
    if (!neo4jConfig) {
      return res.status(400).json({
        success: false,
        message: '缺少 Neo4j 配置参数'
      })
    }
    
    driver = neo4j.driver(
      neo4jConfig.uri,
      neo4j.auth.basic(neo4jConfig.username, neo4jConfig.password)
    )
    
    await driver.verifyConnectivity()
    
    res.json({
      success: true,
      message: 'Neo4j 连接测试成功'
    })
    
  } catch (error) {
    console.error('连接测试失败:', error)
    
    let errorMessage = 'Neo4j 连接测试失败'
    
    if (error.code === 'ServiceUnavailable') {
      errorMessage = 'Neo4j 数据库连接失败，请检查数据库是否运行以及连接配置'
    } else if (error.code === 'Neo.ClientError.Security.Unauthorized') {
      errorMessage = 'Neo4j 认证失败，请检查用户名和密码'
    }
    
    res.status(500).json({
      success: false,
      message: errorMessage,
      error: error.message
    })
  } finally {
    if (driver) {
      await driver.close()
    }
  }
})

app.listen(PORT, () => {
  console.log(`Neo4j Import Server 运行在端口 ${PORT}`)
  console.log(`健康检查: http://localhost:${PORT}/api/health`)
})